#include "widget.h"
#include <QPushButton>
#include <QDebug>
#include <QPushButton>

/**
 * Teacher 类 老师类
 * Student 类 学生类
 * 下课后，老师会触发一个信号，饿了，学生响应信号，请客吃饭。
 * @param parent
 */

Widget::Widget(QWidget *parent)
        : QWidget(parent)
{
    // 创建一个老师对象
    this->zt = new Teacher(this);

    // 创建一个学生对象
    this->st = new Student(this);

    // 老师饿了，学生请客的连接
    // 当信号和槽函数只有一个的时候，无论函数带惨还是无参，都可以用下面的写法
    // 但当有多个时（重载）下面的写法编译器就不知道要调用哪个函数了
//    connect(zt, &Teacher::hungry, st, &Student::treat);

    // 既然参数是函数的地址，那么就可以定义一个函数指针指向函数地址
//    void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
//    void (Student::*studentSlot)(QString) = &Student::treat;
//    connect(zt, teacherSignal, st, studentSlot);

    // 不想定义函数指针变量，就这样写，推荐写法
    connect(zt, static_cast<void (Teacher::*)(QString)>(&Teacher::hungry),
            st, static_cast<void (Student::*)(QString)>(&Student::treat));

    // 调用下课函数
//    classIsOver();
    // 不想一打开窗口，就下课
    // 改为，点击一个下课按钮，再触发下课
    auto *btn = new QPushButton("下课", this);
    // 重置窗口大小
    resize(600, 400);

    // 点击下课按钮，触发下课
    // 方式1：点击按钮，调用槽函数处理
//    connect(btn, &QPushButton::clicked, this, &Widget::classIsOver);

    // 无参信号和槽连接
    connect(zt, static_cast<void (Teacher::*)()>(&Teacher::hungry),
            st, static_cast<void (Student::*)()>(&Student::treat));

    // 方式2： 点击按钮，触发另一个信号
    // 信号连接信号
    connect(btn, &QPushButton::clicked, zt, static_cast<void (Teacher::*)()>(&Teacher::hungry));

    // 断开信号
//    disconnect(zt, static_cast<void (Teacher::*)()>(&Teacher::hungry),
//               st, static_cast<void (Student::*)()>(&Student::treat));

    // 拓展：
    // 1、信号可以连接信号
    // 2、一个信号可以连接多个槽函数
    // 3、多个信号可以连接同一个槽函数
    // 4、信号和槽函数的参数 必须类型一一对应
    // 5、信号和槽函数的参数的个数必须要一致吗？信号的参数个数 可以多于槽函数的参数个数

    // QT4版本以前的信号和槽连接方式
    // 利用QT4信号槽 连接无参版本
//    connect(zt, SIGNAL(hungry()), st, SLOT(treat()));
    // 利用QT信号槽 连接有参版本
//    connect(zt, SIGNAL(hungry(QString)), st, SLOT(treat(QString)));

    // QT4版本连接方式：优点：参数直观，缺点：类型不做检测
    // 下面可以编译通过，但在运行时报错
//    connect(zt, SIGNAL(hungry()), st, SLOT(treat(QString)));

    // 使用lambda表达式，实现点击按钮 关闭窗口
    auto *btn2 = new QPushButton("下课 lambda", this);
    btn2->move(100, 0);
    connect(btn2, &QPushButton::clicked, this, [=]() /* 这里用&程序会崩溃 */ {
//       this->close();
        emit zt->hungry("宫保鸡丁");
        btn2->setText("aaa");
    });
    // 使用lambda的好处，可以在lambda函数体内 调用任意函数
}

Widget::~Widget()
{
}

void Widget::classIsOver()
{
    // 下课函数，调用后，触发老师饿了的信号
//    emit zt->hungry();
    emit zt->hungry("宫保鸡丁");
}
